/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.sequence.ui.composites;

import java.util.Iterator;

import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.gef.EditPart;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.Operation;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.sequence.ui.dialogs.MessageOperationTreeSelectionDialog;
import com.cea.papyrus.diagram.sequence.ui.validators.UMLLabelProvider;
import com.cea.papyrus.tabbedproperties.composites.DecoratedLabelComposite;
import com.cea.papyrus.umlutils.MessageUtil;


public class MessageOperationComposite extends DecoratedLabelComposite {

	/**
	 * debug channel.
	 */
	protected static int channel = 501;

	/**
	 * behavior selected
	 */
	protected Operation operation = null;
	
	protected ITreeContentProvider contentProvider;
	protected LabelProvider labelProvider;
	
	/**
	 * Default Constructor.
	 */
	public MessageOperationComposite(){
		super("Operation");
	}

	/**
	 * Constructor with given name for label.
	 */
	public MessageOperationComposite(String name){
		super(name);
	}

	/**
	 * Property page
	 */
	private TabbedPropertySheetPage tabbedPropertySheetPage = null;
	
	/**
	 * Loads a new property page on the effect
	 */
	@Override
	public void editText(){
		//TODO: find a solution to load a new property page
		if(operation != null){
			EditPart selection = null;
			
			Iterator<EditPart> i = LookForElement.getAllOutlineEditParts().iterator();
			while((selection == null) && i.hasNext()){
				EditPart current = i.next() ;
				if((current.getModel() != null) && current.getModel().equals(operation))
					selection = current ;
			}
			if(selection != null){
				tabbedPropertySheetPage.selectionChanged(getActiveEditor(), new StructuredSelection(selection));
			}
		}
	}

	/**
	 * Stores the tabbed property page before handling the call
	 * to createContent
	 */
	public Composite createContent(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage){
		this.tabbedPropertySheetPage = tabbedPropertySheetPage;
		return createContent(parent, tabbedPropertySheetPage.getWidgetFactory());
	}

	/**
	 * Creates contents.
	 * 
	 * @param parent Composite.
	 * @param factory TabbedPropertySheetWidgetFactory.
	 * 
	 * @return specific Composite.
	 */
	@Override
	public Composite createContent(Composite parent, TabbedPropertySheetWidgetFactory factory){
		Composite composite = super.createContent(parent, factory);

		label.setText("Operation:");
		label.setToolTipText("Operation");
		
		return composite;
	}

	/**
	 * Refreshes the composite.
	 */
	@Override
	public void refresh() {
		Element elt = element.getUml2Element();	
		assert elt != null : 
			"Passed argument is null";
		assert elt instanceof Message : 
			"Passed argument is not a Message";
		
		operation = getMessageOperation();
		if(operation != null){
			if(!text.isDisposed()) {
				text.setImage(labelProvider.getImage(operation));
				text.setText(labelProvider.getText(operation));
			}
			if(!addButton.isDisposed())
				addButton.setEnabled(false);
			if(!removeButton.isDisposed())
				removeButton.setEnabled(true);
		}
		else{
			if(!text.isDisposed()){
				text.setText("Operation Unset");
				text.setImage(null);
			}
			if(!addButton.isDisposed())
				addButton.setEnabled(true);
			if(!removeButton.isDisposed())
				removeButton.setEnabled(false);
		}
	}

	/**
	 * Executed behavior when addButton pressed.
	 */
	public void addButtonPressed(){
		Element elt = element.getUml2Element();	
		assert elt != null : 
			"Passed argument is null";
		assert elt instanceof Message : 
			"Passed argument is not a Message";
		
		int result;
		Message message = ((Message) elt);
		MessageOperationTreeSelectionDialog dialog = 
			new MessageOperationTreeSelectionDialog(
					composite.getShell(), 
					labelProvider,
					contentProvider,
					message);

		dialog.setInput(message.getModel());				
		result = dialog.open();
			
			
		// result treatment
		if(result==IDialogConstants.OK_ID) {
			Operation selection = (Operation) dialog.getFirstResult();
				
			// Set operation
			setMessageOperation(selection);	
		}
	}

	/**
	 * Executed behavior when removeButton pressed.
	 */
	public void removeButtonPressed(){
		Element elt = element.getUml2Element();	
		assert elt != null : 
			"Passed argument is null";
		assert elt instanceof Message : 
			"Passed argument is not a Message";

		if(!text.isDisposed())
			text.setText("Operation Unset");

		operation = getMessageOperation();
		if(operation != null) {
			setMessageOperation(null);
		}

		//refresh contents
		refresh();
	}

	public void setContentProvider(ModelManager modelManager) {
		this.contentProvider = 
			new AdapterFactoryContentProvider(modelManager.getAdapterFactory());
	}
	
	public void setLabelProvider(ModelManager modelManager) {
		this.labelProvider = new UMLLabelProvider(modelManager.getLabelProvider());
	}

	private Operation getMessageOperation() {
		return MessageUtil.getMessageOperation((Message) element.getUml2Element());
	}
	
	private void setMessageOperation(Operation newOperation) {
		MessageUtil.setMessageOperation((Message) element.getUml2Element(), newOperation);
	}
}
